// 实现这个项目的构建任务
/*
 * 实现思路
 * 1. 对css,js,html等文件编译，如style,script,page,font,image,public等任务
 * 2. 启动一个本地web服务运行项目，本地修改文件，浏览器实时热更新。   ps: 端口不要用6666，会提示页面找不到的，坑
 * 3. build出来的文件, 对文件内引用链接处理, 并且压缩格式化
 * 4. 提取路径数据等配置，在外面使用时可以自行传入参数,
 * 5. 导出方法
 *      1. clean, 清除build出来的文件
 *      2. serve, 启动本地服务，运行项目
 *      3. build, 打包项目文件，并且压缩格式化
 * */

const { src, dest, parallel, series, watch } = require('gulp')

const del = require('del')

const loadPlugins = require('gulp-load-plugins')
const plugin = loadPlugins()
const { sass, babel, swig, imagemin, uglify, htmlmin, useref, cleanCss } = plugin

const bs = require('browser-sync')

// 命令行运行的所在目录
const cwd = process.cwd()
console.log('cwd', cwd)

// 命令行 的 参数
const argv = process.argv
console.log('argv', argv)

let config = {
  data: {},
  build: {
    src: 'src',
    dist: 'dist',
    temp: '.temp',
    public: 'public',
    paths: {
      styles: 'assets/styles/*.scss',
      scripts: 'assets/scripts/*.js',
      pages: '*.html',
      images: 'assets/images/**',
      fonts: 'assets/fonts/**',
    },
  },
}
try {
  const configjs = require(`${cwd}/page.config.js`)
  config = Object.assign({}, config, configjs)
} catch (error) {}
// console.log('config', config)

const baseSrc = { base: config.build.src, cwd: config.build.src }

// { base: 'src' } 可以跟src目录有同样的层级目录

// css文件
const style = () => {
  return src(config.build.paths.styles, baseSrc)
    .pipe(sass({ outputStyle: 'expanded' }))
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream: true }))
}

// js文件
const script = () => {
  return src(config.build.paths.scripts, baseSrc)
    .pipe(babel({ presets: [require('@babel/preset-env')] }))
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream: true }))
}

// HTML页面
const page = () => {
  return src(config.build.paths.pages, baseSrc)
    .pipe(swig({ data: config.data, defaults: { cache: false } }))
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream: true }))
}

// 图片
const image = () => {
  return src(config.build.paths.images, baseSrc).pipe(imagemin()).pipe(dest(config.build.dist))
}

// font字体文件
const font = () => {
  return src(config.build.paths.fonts, baseSrc).pipe(imagemin()).pipe(dest(config.build.dist))
}

//导入其他文件
const public = () => {
  return src('**', { base: config.build.public, cwd: config.build.public }).pipe(dest(config.build.dist))
}

// 启动一个web服务器
const server = () => {
  watch(config.build.paths.styles, { cwd: config.build.src }, style)
  watch(config.build.paths.pages, { cwd: config.build.src }, page)
  watch(config.build.paths.scripts, { cwd: config.build.src }, script)

  watch([config.build.paths.images, config.build.paths.fonts], { cwd: config.build.src }, bs.reload)

  watch('**', { cwd: config.build.public }, bs.reload)

  bs.init({
    notify: false,
    // 此处一坑，端口6666是页面访问不存在
    port: 6060,
    open: false,
    // files: config.temp,
    server: {
      baseDir: [config.build.temp, config.build.src, config.build.public],
      routes: {
        '/node_modules': 'node_modules',
      },
    },
  })
}

// 打包上线前，对html,css,js等文件进行压缩格式化
const userefs = () => {
  return src(config.build.paths.pages, { base: config.build.temp, cwd: config.build.temp })
    .pipe(useref({ searchPath: [config.build.temp, '.'] }))
    .pipe(plugin.if(/\.js$/, uglify()))
    .pipe(plugin.if(/\.css$/, cleanCss()))
    .pipe(
      plugin.if(
        /\.html$/,
        htmlmin({
          collapseWhitespace: true,
          minifyCSS: true,
          minifyJS: true,
        })
      )
    )
    .pipe(dest(config.build.dist))
}

// 清除打包出来的文件
const clean = () => del([config.build.dist, config.build.temp])

// parallel 并行任务
// series 串行任务
const compile = parallel(style, script, page)

const build = series(clean, parallel(series(compile, userefs), image, font, public))

const serve = series(compile, server)

module.exports = {
  clean,
  serve,
  build,
}
